package com.zhenyi.xhc.core;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

import org.hashids.Hashids;

import com.jfinal.kit.JsonKit;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.Ret;
import com.jfinal.weixin.sdk.api.PaymentApi;
import com.utils.DateUtils;
import com.utils.PathUtils;
import com.xhc.common.model.XhcOrder;
import com.xhc.common.model.XhcTicket;
import com.xhc.common.model.XhcUserPresent;
import com.xhc.common.model.XhcUserTicket;
import com.zhenyi.xiaohuche.utils.PayUtils;

import cn.hutool.core.util.HexUtil;
import cn.hutool.setting.Setting;

public class OrderUtils {

	protected Setting setting = new Setting("xhc.setting");
	protected Hashids piaoHashids = new Hashids("piao", 8);
	protected final String SECRET = PropKit.get("XHC_APP_SECRET", "");
	protected final String APP_ID = PropKit.get("XHC_APP_ID", "");
	protected final String PARTNER = PropKit.get("XHC_PARTNER", "");
	protected final String NOTIFY_URL = PropKit.get("XHC_NOTIFY_URL", "");
	protected final String REFUND_NOTIFY_URL = PropKit.get("XHC_REFUND_NOTIFY_URL", "");
	protected final String PARTNER_KEY = PropKit.get("XHC_PARTNER_KEY", "");
	// protected String SSL_PATH =
	// XHCPathUtils.getClassFile("wx6d47db34d18f5e3a", "apiclient_cert.p12");;
	String SSL_PATH = PathUtils.getFile("cert", APP_ID, "apiclient_cert.p12");
	protected PayUtils payUtils = new PayUtils(APP_ID, PARTNER, PARTNER_KEY, SSL_PATH);
	protected String HOST = setting.getStr("host", "ticketSetting", "");
	protected String QRCODE_HOST = setting.getStr("qrcode", "ticketSetting", "");
	protected String QRCODE_VERIFY = setting.getStr("verify", "ticketSetting", "");
	protected final int REFUND_TIME = setting.getInt("refundTime", "ticketSetting", 7200000);
	private static final Hashids hashids = new Hashids("order", 3);

	public static String gen(Long id) {

		String timestamp = DateUtils.dateFormat(new Date(), "yyyyMMddHHmmss");
		// int prefix = 1000 + type;
		String en = hashids.encode(id);
		String ran = HexUtil.encodeHexStr(en);
		return timestamp + ran;
	}

	public static Long decode(String no) {
		try {
			String hex = no.substring(14, no.length());
			String code = HexUtil.decodeHexStr(hex);
			return hashids.decode(code)[0];
		} catch (Exception e) {
			LogKit.error("decode order no fail");
			return null;
		}
	}

	/**
	 * 在规定时间内退票
	 * 
	 * @param ticket
	 * @return
	 */
	private boolean canRefund(XhcTicket ticket) {
		Date now = new Date();
		// System.out.println(now);
		// System.out.println(ticket.getTime());
		// System.out.println(now.getTime());
		// System.out.println(ticket.getTime().getTime());
		// System.out.println(ticket.getTime().getTime() - now.getTime());
		System.out.println(REFUND_TIME);
		if (ticket.getTime().getTime() - now.getTime() <= REFUND_TIME) {
			return false;
		}
		return true;
	}

	/**
	 * 退款
	 * 
	 * @param controller
	 * @param id
	 * @param isForce
	 *            是否强制退款
	 */
	public void refundTicket(XHCController controller, Long id, boolean isForce) {

		XhcUserTicket userTicket = XhcUserTicket.dao.findById(id);
		if (userTicket == null) {
			controller.renderFailure("userTicket error");
			return;
		}
		XhcTicket ticket = XhcTicket.dao.findById(userTicket.getTicketId());
		if (ticket == null) {
			controller.renderFailure("ticket error");
			return;
		}
		// if (!isForce && !canRefund(ticket)) {
		// LogKit.info("请在规定时间内退票");
		// controller.renderMsg("请在规定时间内退票");
		// return;
		// }
		Integer status = userTicket.getStatus();
		controller.renderFailure();
		// if (!status.equals(1)) {
		// LogKit.info("非已支付状态,不退款");
		// return;
		// }
		BigDecimal paid = userTicket.getPaid();
		XhcOrder order = XhcOrder.dao.findById(userTicket.getOrderId());
		Map<String, String> query = PaymentApi.queryByOutTradeNo(APP_ID, PARTNER, PARTNER_KEY, order.getOutTradeNo());
		if (PropKit.getBoolean("devMode", false)) {
			System.out.println(JsonKit.toJson(query));
		}
		String trade_state = query.get("trade_state");
		if (!("REFUND".equals(trade_state) || "SUCCESS".equals(trade_state))) {
			LogKit.info("订单支付状态非SUCCESS");
			controller.renderFailure("订单支付状态非SUCCESS");
			return;
		}
		String refundNo = id + "-refund-" + paid.intValue();
		String out_trade_no = order.getOutTradeNo();
		// String cash_fee = getCashFee();
		String total_fee = order.getPaid() + "";

		String refundFee = userTicket.getPaid().toString();
		if (PropKit.getBoolean("devMode", false)) {
			refundFee = "1";
		}
		Map<?, ?> refund = payUtils.refundOrderNo(out_trade_no, total_fee, refundFee, refundNo, REFUND_NOTIFY_URL);

		boolean flag = PayUtils.isXMLSuccess(refund);

		if (flag) {
			userTicket.setStatus(-1);
			userTicket.update();
			order.updateOrderStatus();
			controller.renderSuccess();
			return;
		} else {
			LogKit.warn(JsonKit.toJson(refund));
			String err_code_des = String.valueOf(refund.get("err_code_des"));
			// controller.renderFailure("退票失败");
			// controller.renderFailure(err_code_des);
			controller.renderMsg(err_code_des);
			return;
		}
	}

	public void refundTicket(XHCController controller, Long id) {
		refundTicket(controller, id, false);
	}

	public void refundPresent(XHCController controller, Long id) {
		XhcUserPresent userPresent = XhcUserPresent.dao.findById(id);
		if (userPresent == null) {
			controller.renderFailure();
			return;
		}
		if (!userPresent.getStatus().equals(1)) {
			controller.renderMsg("无法退款");
			LogKit.info("非已支付状态,不退款");
			return;
		}
		XhcOrder order = XhcOrder.dao.findById(userPresent.getOrderId());
		BigDecimal paid = userPresent.getPaid();
		Map<String, String> query = PaymentApi.queryByOutTradeNo(APP_ID, PARTNER, PARTNER_KEY, order.getOutTradeNo());
		String trade_state = query.get("trade_state");
		if (!(trade_state.equals("SUCCESS") || trade_state.equals("REFUND"))) {
			LogKit.info("订单支付状态非SUCCESS");
			controller.renderFailure("订单支付状态非SUCCESS");
			return;
		}
		String refundNo = id + "-refundPresent-" + paid.intValue();
		String out_trade_no = order.getOutTradeNo();
		String total_fee = order.getPaid() + "";
		Map<?, ?> refund = payUtils.refundOrderNo(out_trade_no, total_fee, total_fee, refundNo, REFUND_NOTIFY_URL);
		boolean flag = PayUtils.isXMLSuccess(refund);

		if (flag) {
			controller.renderSuccess();
			return;
		} else {
			String err_code_des = String.valueOf(refund.get("err_code_des"));
			LogKit.warn(JsonKit.toJson(refund));
			// controller.renderFailure("退票失败");
			controller.renderFailure(err_code_des);
			return;
		}
	}

	public Ret refund(String out_trade_no, String total_fee) {
		String refundNo = out_trade_no + "-refundPresent-RF";
		Map<?, ?> refund = payUtils.refundOrderNo(out_trade_no, total_fee, total_fee, refundNo, REFUND_NOTIFY_URL);
		boolean flag = PayUtils.isXMLSuccess(refund);
		if (flag) {
			return Ret.ok("refund", refund);
		} else {
			return Ret.fail("refund", refund);
		}
	}
}
